package other;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpStatus;
import com.nlf.calendar.Lunar;
import com.nlf.calendar.Solar;

import java.time.LocalDate;
import java.time.YearMonth;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期工具类
 *
 * @author superC
 * @version 2.0.0
 * @date 2024/3/17
 */

public class MyDateUtil {

    public static final String SEPARATOR_BLACK = " ";

    public static final String INIT_MONTH_FIRST = "-01";
    public static final String INIT_MONTH_END = "-12";
    public static final String INIT_DAY_FIRST = "-01";
    public static final String INIT_TIME_FIRST = " 00:00:00";
    public static final String INIT_TIME_END = " 23:59:59";

    /**
     * 判断指定日期是否在今天之前
     *
     * @param target 指定日期
     */
    public static boolean isBeforeYear(LocalDate target) {
        return diffYear(target) < 0;
    }

    /**
     * 判断指定日期是否在今天之前
     *
     * @param target 指定日期
     */
    public static boolean isBeforeToday(LocalDate target) {
        return diffDay(target) < 0;
    }

    /**
     * 判断指定日期所在年份是否在今年之后（包含今年）
     *
     * @param target 指定日期
     */
    public static boolean isAfterYear(LocalDate target) {
        return diffYear(target) >= 0;
    }

    /**
     * 判断指定日期是否在今天之后
     *
     * @param target 指定日期
     */
    public static boolean isAfterToday(LocalDate target) {
        return diffDay(target) >= 0;
    }

    /**
     * 缴费阈值：下次缴费日距今不足一个月
     *
     * @param payDate 缴费日
     */
    public static boolean isStartExpire(LocalDate payDate) {
        // 计算至今的天数，是否不足一个月
        return diffDay(payDate) < 30;
    }

    /**
     * 获取指定时间与当前时间的间隔
     *
     * @param time 指定时间字符串（格式为HH:mm:ss）
     * @return 间隔小时，不足1小时返回0；
     */
    public static int hourInterval(String time) {
        String targetTime = DateUtil.today() + time;
        // 使用Hutool计算两个时间点之间的小时时长
        return (int) DateUtil.between(DateUtil.parse(targetTime), new DateTime(), DateUnit.HOUR);
    }

    /**
     * 判断指定日期是否小于等于今天
     *
     * @param targetDate 日期字符串
     * @return
     */
    public static boolean isBeforeToday(String targetDate) {
        return DateUtil.compare(DateUtil.parse(targetDate + INIT_TIME_FIRST), new DateTime()) <= 0;
    }

    /**
     * 判断指定日期是否大于等于今天
     *
     * @param targetDate 日期字符串
     * @return
     */
    public static boolean isAfterToday(String targetDate) {
        return DateUtil.compare(DateUtil.parse(targetDate + INIT_TIME_END), new DateTime()) >= 0;
    }

    /**
     * 获取一周前的日期
     */
    public static String getWeekBeforeDate() {
        Date oneWeekAgo = DateUtil.offsetDay(new Date(), -7);
        return DateUtil.formatDate(oneWeekAgo);
    }

    /**
     * 阴历转阳历日期
     *
     * @param year  阴历日期-年
     * @param month 阴历日期-月
     * @param day   阴历日期-日
     * @return
     */
    public static LocalDate lunar2Solar(int year, int month, int day) {
        Lunar lunar = new Lunar(year, month, day);
        Solar solar = lunar.getSolar();
        String ymd = solar.toYmd();
        System.out.println(ymd);
        System.out.println("转换后的LocalDate是: " + LocalDate.parse(ymd));
        return LocalDate.parse(ymd);
    }

    /**
     * 天数差值：今天距指定日期的天数
     *
     * @param date 所传日期
     */
    public static int diffDay(LocalDate date) {
        // 计算至今的天数
        return (int) ChronoUnit.DAYS.between(LocalDate.now(), date);
    }

    /**
     * 年份差值（绝对值）：计算所传年份与今年的年长
     *
     * @param year 所传年份
     */
    public static int diffYear(Integer year) {
        return Math.abs(DateUtil.thisYear() - year);
    }

    /**
     * 年份差值：计算所传日期与今年的年长
     * 说明：当所传日期不在今年，且所传的日期（MM-dd）比今天的日期（MM-dd）小，则计算的年份要减1；
     *
     * @param date 所传日期
     * @return 若返回负数，表示所传日期在今年之前；若返回0，表示当前日期为今年；若返回正数，表示所传日期在今年之后；
     */
    public static int diffYear(LocalDate date) {
        // 计算至今的年长
        return (int) ChronoUnit.YEARS.between(LocalDate.now(), date);
    }

    /**
     * 计算月份差：计算输入年月与今天的月份差
     */
    public static int diffMonth(String yearMonth) {
        // 输入年月
        YearMonth startYearMonth = YearMonth.parse(yearMonth);

        // 当前日期
        YearMonth endYearMonth = YearMonth.now();

        //获取两个日期之间的月份的差
        long months = ChronoUnit.MONTHS.between(startYearMonth, endYearMonth);
        return Math.toIntExact(months);
    }

    /**
     * 获取指定年月的最后一天
     *
     * @param yearMonth
     */
    public static String getLastMonthDay(String yearMonth) {
        Date monthLastDay = DateUtil.endOfMonth(DateUtil.parse(yearMonth, DatePattern.NORM_MONTH_PATTERN));
        return DateUtil.formatDate(monthLastDay);
    }

    /**
     * 获取当前日期指定月数后的日期
     * 将输入的日期：月份 + monthStep，日重置为1号
     * 示例：2023-01-31 + 1 = 2023-02-01
     *
     * @param monthStep 月份步长
     */
    public static Date getFutureMonth(Date targetDate, int monthStep) {
        final int num = 1;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(targetDate);
        calendar.add(Calendar.MONTH, monthStep);
        calendar.set(Calendar.DAY_OF_MONTH, num);
        return calendar.getTime();
    }

    /**
     * 将日期转化为年月字符串
     *
     * @param targetDate 日期，格式为yyyy-MM-dd
     * @return 年月，字符串格式为yyyy-MM
     */
    public static String format2Month(Date targetDate) {
        return DateUtil.format(targetDate, DatePattern.NORM_MONTH_PATTERN);
    }

    public static Date parse2Month(String yearMonth) {
        return DateUtil.parse(yearMonth, DatePattern.NORM_MONTH_PATTERN);
    }

    /**
     * 获取本月
     */
    public static String getThisMonth() {
        return MyDateUtil.format2Month(new Date());
    }

    /**
     * 日期比较
     *
     * @param sourceDate
     * @param targetDate
     * @return -1，表示source在target之前；0，表示相等；1，表示source在target之后；
     */
    public static int compareMonth(String sourceDate, String targetDate) {
        Date date1 = MyDateUtil.parse2Month(sourceDate);
        Date date2 = MyDateUtil.parse2Month(targetDate);
        return date1.compareTo(date2);
    }

    /**
     * 获取开始日期
     *
     * @param dateType  日期类型
     * @param startDate 开始日期字符串
     */
    public static Date getStartDate(Integer dateType, String startDate) {
        if (DateTypeEnum.DAY.getCode().equals(dateType)) {
            return DateUtil.parseDate(startDate);
        } else if (DateTypeEnum.MONTH.getCode().equals(dateType)) {
            return DateUtil.parseDate(startDate + INIT_DAY_FIRST);
        } else if (DateTypeEnum.YEAR.getCode().equals(dateType)) {
            return DateUtil.parseDate(startDate + INIT_MONTH_FIRST + INIT_DAY_FIRST);
        } else {
            return null;
        }
    }

    /**
     * 获取开始日期
     *
     * @param dateType 日期类型
     * @param endDate  开始日期字符串
     */
    public static Date getEndDate(Integer dateType, String endDate) {
        if (DateTypeEnum.DAY.getCode().equals(dateType)) {
            return DateUtil.parseDate(endDate);
        } else if (DateTypeEnum.MONTH.getCode().equals(dateType)) {
            return DateUtil.endOfMonth(MyDateUtil.parse2Month(endDate));
        } else if (DateTypeEnum.YEAR.getCode().equals(dateType)) {
            return DateUtil.endOfYear(DateUtil.parseDate(endDate + INIT_MONTH_FIRST + INIT_DAY_FIRST));
        } else {
            return null;
        }
    }

    public static DateTime getEndTime(Integer dateType, String endDate) {
        return DateUtil.parse(DateUtil.formatDate(getEndDate(dateType, endDate)) + INIT_TIME_END, DatePattern.NORM_DATETIME_FORMATTER);
    }

}
